/**
 * 等待一个结果为真的情况执行
 */
import {dynamicObj} from "../types";

export function waitValue (valueGetter: Function, timeout = 10000, freq = 100) {
    return new Promise((resolve,reject) => {
        let count = 0
        let timerId = setInterval(() => {
            if(count*freq > timeout) {
                clearInterval(timerId)
                reject('等待超时')
            }
            if(valueGetter()) {
                clearInterval(timerId)
                resolve(valueGetter())
            }
            count++
        }, freq)
    })
}

/**
 * 等待固定毫秒数
 * @param ms
 */
export async function waitMS (ms) {
    return new Promise(resolve => {
        setTimeout(resolve, ms)
    })
}

/**
 * 一个变化代理，如果一段时间内反复横跳，则取最后，相当于节流防抖的赋值代理版本。
 * 应用场景：解决loading状态在多处频繁变化
 */
export function lazyChange (obj, timeout = 100) {
    let timer = null
    const handler: ProxyHandler<any> = {
        set: (target: dynamicObj, key: string, value: any) => {
            if(!timer) target[key] = value
            else clearTimeout(timer)
            timer = setTimeout(() => {target[key] = value}, timeout)
            return true
        }
    }
    return new Proxy(obj, handler)
}

/**
 * async防抖函数，接收一个async函数，返回节流的async函数
 * 先执行一次，timeout毫秒内在发生调用则忽视，timeout后才可继续调用
 */
export function throttleAsync(func: Function, timeout = 100) {
    let lastTime = 0
    return async function(...args) {
        const now = Date.now()
        if(now - lastTime < timeout) {
            return
        }
        lastTime = now
        return await func(...args)
    }
}

/**
 * 接收一个async函数，返回新的async函数
 * 至少freq毫秒后触发该函数，freq内再次触发，取消前一次触发，直到freq毫秒内没有触发，正式执行这个函数
 */
export function debounceAsync(func: Function, wait = 100) {
    let timer = null
    return function(...args) {
        if(timer) clearTimeout(timer)
        timer = setTimeout(() => {
            func(...args)
        }, wait)
    }
}

/**
 * 轮询工具
 */
export class Poll {
    func: Function
    freq: number
    timer: NodeJS.Timeout
    constructor() {
        this.timer = null
        this.func = () => {}
        this.freq = 1000
    }
    init() {
        if(this.timer) return
        this.func()
        this.timer = setInterval(() => {
            this.func()
        },this.freq)
    }
    destroy() {
        clearInterval(this.timer)
        this.timer = null
    }
}
export default {
    waitValue, Poll, lazyChange, throttleAsync, debounceAsync
}
